﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using AMM.Model;
using AMM.Model.Store;

namespace AMM.DataAccess.Store {
    public class ProductInStoreOrderRepository : BaseRepository<ProductInStoreOrder> {

        private int _pageSize;

        public ProductInStoreOrderRepository(int pageSize) {
            this._pageSize = pageSize;
        }

        public ProductInStoreOrder FetchProductInStoreOrderById(int productInStoreOrderId) {
            using (var ctx = this.Context) {
                return ctx.ProductInStoreOrders
                    .FirstOrDefault(x => x.ProductInStoreOrderId == productInStoreOrderId);
            }
        }

        public ProductInStoreOrder FetchProductInStoreOrderByIdForView(int productInStoreOrderId) {
            using (var ctx = this.Context) {
                return ctx.ProductInStoreOrders
                    .Include("ProduceConduct")
                    .FirstOrDefault(x => x.ProductInStoreOrderId == productInStoreOrderId);
            }
        }

        public void UpdateProductInStoreOrder(ProductInStoreOrder productInStoreOrder) {
            using (var ctx = this.Context) {
                using (DbContextTransaction trans = ctx.Database.BeginTransaction()) {
                    try {
                        // Add store amount
                        List<ProductStore> existPSList =
                            ctx.ProductStores.Where(x => x.StoreBasisId == productInStoreOrder.StoreBasisId).ToList();
                        ProductStore ps = existPSList.FirstOrDefault(x => x.ProductId == productInStoreOrder.ProductId);
                        if (ps == null) {
                            ps = new ProductStore() {
                                ProductStoreId = Guid.NewGuid().GetHashCode(),
                                ProductId = productInStoreOrder.ProductId,
                                StoreBasisId = productInStoreOrder.StoreBasisId,
                                Quantity = productInStoreOrder.Quantity,
                                InStoreTotal = productInStoreOrder.Quantity
                            };
                            ctx.ProductStores.Attach(ps);
                            ctx.Entry(ps).State = EntityState.Added;
                        }
                        else {
                            ps.Quantity += productInStoreOrder.Quantity;
                            ps.InStoreTotal += productInStoreOrder.Quantity;
                            ctx.ProductStores.Attach(ps);
                            ctx.Entry(ps).State = EntityState.Modified;
                        }

                        ctx.ProductInStoreOrders.Add(productInStoreOrder);
                        ctx.Entry(productInStoreOrder).State = EntityState.Modified;

                        ctx.SaveChanges();
                        trans.Commit();
                    }
                    catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public void DeleteMultipleProductInStoreOrder(params int[] productInStoreOrderIds) {
            using (var ctx = this.Context) {
                using (DbContextTransaction trans = ctx.Database.BeginTransaction()) {
                    try {
                        ctx.ProductInStoreOrders.Where(x => productInStoreOrderIds.Contains(x.ProductInStoreOrderId)).ToList().ForEach(x => {
                            ctx.ProductInStoreOrders.Remove(x);
                        });
                        ctx.SaveChanges();
                        trans.Commit();
                    }
                    catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public List<ProductInStoreOrder> FetchProductInStoreOrderList(ProductInStoreOrderSearchModel searchModel, int pageIndex) {
            using (var ctx = this.Context) {
                var query = ctx.ProductInStoreOrders
                    .Include("Basic")
                    .Include("Basic1")
                    .Include("StoreBasi")
                    .Include("ProduceConduct")
                    .Include("Product")
                    .Include("Vendor")
                    .Where(x => !string.IsNullOrEmpty(x.Code));

                if (!string.IsNullOrEmpty(searchModel.ProductInStoreOrderCode)) {
                    query = query.Where(x => x.Code.Contains(searchModel.ProductInStoreOrderCode));
                }
                if (!string.IsNullOrEmpty(searchModel.ProduceConductCode)) {
                    query = query.Where(x => x.ProduceConduct.Code.Contains(searchModel.ProduceConductCode));
                }
                if (!string.IsNullOrEmpty(searchModel.ProductCode)) {
                    query = query.Where(x => x.Product.Code.Contains(searchModel.ProductCode));
                }
                if (searchModel.ProductInStoreDateStart.HasValue) {
                    query = query.Where(x => x.CreatedDatetime >= DbFunctions.TruncateTime(searchModel.ProductInStoreDateStart.Value));
                }
                if (searchModel.ProductInStoreDateEnd.HasValue) {
                    query = query.Where(x => x.CreatedDatetime <= DbFunctions.TruncateTime(searchModel.ProductInStoreDateEnd.Value));
                }
                if (searchModel.ProductInStoreTypeId.HasValue) {
                    query = query.Where(x => x.InStoreTypeId == searchModel.ProductInStoreTypeId.Value);
                }
                if (searchModel.StoreBasisId.HasValue) {
                    query = query.Where(x => x.StoreBasisId == searchModel.StoreBasisId.Value);
                }
                if (searchModel.ProduceUnitId.HasValue) {
                    query = query.Where(x => x.ProduceUnitId == searchModel.ProduceUnitId.Value);
                }
                if (searchModel.OrderStatus.HasValue) {
                    query = query.Where(x => x.Status == searchModel.OrderStatus.Value);
                }

                searchModel.Records = query.Count();
                pageIndex = (pageIndex - 1) * this._pageSize > searchModel.Records ? 1 : pageIndex;

                return query.OrderByDescending(x => x.CreatedDatetime).Skip((pageIndex - 1) * this._pageSize).Take(this._pageSize).ToList();
            }
        }

        public int GetTheMaxFlowNumber(string startString) {
            using (var ctx = this.Context) {
                ProductInStoreOrder productInStoreOrder = ctx.ProductInStoreOrders
                    .Where(x => x.Code.StartsWith(startString))
                    .OrderByDescending(x => x.Code)
                    .FirstOrDefault();
                int maxFlowNumber = productInStoreOrder == null
                    ? 0
                    : Convert.ToInt32(productInStoreOrder.Code.Substring(productInStoreOrder.Code.Length - 2, 2));
                return Math.Max(ctx.ProductInStoreOrders.Count(x => x.Code.StartsWith(startString)), maxFlowNumber);
            }
        }
    }
}
